﻿using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using TIBCO.Rendezvous;
using Message = System.ServiceModel.Channels.Message;

namespace Tibco.ServiceModel
{
    internal sealed class TibcoOutputChannel : TibcoOutputChannelBase
    {
        private TibcoTransportBindingElement m_bindingElement;

        private MessageEncoder m_encoder;

        private CMTransport m_cmTransport;

        public TibcoOutputChannel(BindingContext context, CMTransport cmTransport, EndpointAddress address) : base(context, address)
        {
            this.m_bindingElement = context.Binding.Elements.Find<TibcoTransportBindingElement>();
            MessageEncodingBindingElement messageEncodingBindingElement = context.Binding.Elements.Find<MessageEncodingBindingElement>();
            if (messageEncodingBindingElement != null)
            {
                this.m_encoder = messageEncodingBindingElement.CreateMessageEncoderFactory().Encoder;
            }
            this.m_cmTransport = cmTransport;
        }

        public override void Close(TimeSpan timeout)
        {
            if (base.State == CommunicationState.Closed || base.State == CommunicationState.Closing)
            {
                return;
            }
            base.OnClosing();
            base.OnClosed();
        }

        public override void Open(TimeSpan timeout)
        {
            if (base.State != CommunicationState.Created && base.State != CommunicationState.Closed)
            {
                throw new InvalidOperationException(string.Format("Cannot open the channel from the {0} state.", base.State));
            }
            base.OnOpening();
            base.OnOpened();
        }

        public override void Send(Message message, TimeSpan timeout)
        {
            if (message.State != MessageState.Closed)
            {
                byte[] array = null;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    this.m_encoder.WriteMessage(message, memoryStream);
                    array = memoryStream.ToArray();                   
                }

                var s = System.Text.Encoding.UTF8.GetString(array, 0, array.Length);
                var msg = new TIBCO.Rendezvous.Message();
                msg.SendSubject = base.RemoteAddress.Uri.PathAndQuery.Replace("/", "").Replace("-", "");
                msg.AddField("DATA", s);
                this.m_cmTransport.Send(msg);

                Debug.Out("TibcoOutputChannel.Send()", s);
            }
        }
    }
}